package com.lry.util.tree;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 生成树抽象方法
 *
 * @author 李瑞益
 */
public abstract class AbstractTreeArith<T> implements ITreeArithmetic<T>{

    /**
     * 对指定条件下的数据生成树
     * @param parentId 指定生成树的父id
     * @return 指定条件下的树
     */
    @Override
    public List<TreeNode> build(List<T> list, String parentId) {
        //解析列表
        List<TreeNode> sourceList = null;
        try {
            sourceList = getTreeList(list);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return createTree(parentId,sourceList);
    }

    public List<TreeNode> buildChild(List<T> list, String parentId){
        //解析列表
        List<TreeNode> sourceList = null;
        try {
            sourceList = getTreeList(list);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return createTree(parentId,sourceList);
    }

    /**
     * 生成完整树
     * 1.先找到父节点 - 》 改为 先查找父级对应的子集
     * 2.通过父节点找下级
     * @param parentId 父级id
     * @param sourceList 源数据列表
     * @return 数列表
     */
    private List<TreeNode> createTree(String parentId, List<TreeNode> sourceList) {
        if (sourceList == null) {
            return new ArrayList<>();
        }
        List<TreeNode> parentList = null;
        if (parentId == null) {
            parentList = sourceList.stream()
                    .filter(c -> "".equals(c.getParentId()) || c.getParentId() == null).collect(Collectors.toList());
        }else {
            //筛选出指定的id列表
            parentList = sourceList.stream()
                    .filter(c -> parentId.equals(c.getParentId())).collect(Collectors.toList());
        }
        List<TreeNode> treeList = new ArrayList<>();
        //每一个对象都可以能是一个父节点
        for (TreeNode map : parentList) {
            treeList.add(createTree(map,sourceList));
        }
        treeList = treeList.stream().sorted(Comparator.comparing(TreeNode::getSort)).collect(Collectors.toList());
        return treeList;
    }

    /**
     * 生成当前节点
     * @param tree 当的节点对象
     * @return 当前级及一些的树
     */
    private TreeNode createTree(TreeNode tree, List<TreeNode> sourceList) {
        //获取下级结点
        List<TreeNode> filterList = sourceList.stream()
                .filter(c->c.getParentId().equals(tree.getId())).collect(Collectors.toList());
        //当没有下级列表时将作为树叶
        if (filterList.size() == 0) {
            return tree;
        }else{
            List<TreeNode> children = new ArrayList<>();
            //下级节点
            for (TreeNode nextMap : filterList) {
                children.add(createTree(nextMap,sourceList));
            }
            children = children.stream().sorted(Comparator.comparing(TreeNode::getSort)).collect(Collectors.toList());
            tree.setChildren(children);
            return tree;
        }
    }

    /**
     * 数据列表转换为节点列表
     * @param list 源数据列表
     * @return 我们需要对象列表
     */
    private List<TreeNode> getTreeList(List<T> list) throws IllegalAccessException {
        List<TreeNode> mapList = new ArrayList<>();
        for (T t : list) {
            TreeNode tree = (TreeNode) getTreeNode(t);
            //排除自身id= parentId的情况，不然会在递归判断中循环id=parentId的节点
            if (tree.getId().equals(tree.getParentId())) {
                tree.setParentId("-1");
            }
            mapList.add(tree);
        }
        return mapList;
    }

    /**
     * 获取节点
     * @param t 实体对象
     */
    public abstract Object getTreeNode(T t) throws IllegalAccessException;
}
